home *** CD-ROM | disk | FTP | other *** search
/ Celestin Apprentice 2 / Apprentice-Release2.iso / Source Code / C / Snippets / SAVRGestalt / SAVRGestalt.c < prev   
Encoding:
C/C++ Source or Header  |  1994-11-05  |  7.2 KB  |  217 lines  |  [TEXT/MMCC]

  1. /* ================================================= */
  2. /* ================== SAVRGestalt.c ================ */
  3. /* ================================================= */
  4.  
  5. #include <GestaltEqu.h>    // for Gestalt
  6. #include <A4Stuff.h>       // for globals in your code resource
  7. #include <OSUtils.h>
  8.  
  9. // These were defined in AfterDarkGestalt.h
  10. // I don't remember why I didn't just #include it
  11. #define kMySaverOn    0x00000001
  12. #define kMySaverOff   0x00000000
  13.  
  14. #define NIL          0L
  15.  
  16. // type definition for the SAVR Gestalt function
  17. typedef pascal OSErr (*GestaltFunctionPtr) (OSType gestaltSelector,
  18.                                             long *gestaltResponse);
  19.  
  20. Boolean     gSaverOn;  // TRUE if you want this Gestalt to work, FALSE otherwise
  21. long     gOldGestaltAddr, gMyAddr;  // addresses of important stuff
  22.  
  23. /*
  24.    main() gets called when you call the code resource.  In my case, main
  25.    has been set up to return the addresses of the other two functions
  26.    in the code resource, so that the program can call them.
  27. */
  28. void main(long *gestaltAddr, long *setVarsAddr);
  29.  
  30. /*
  31.    SetVars() allows the program to set globals in the code resource.
  32.    You can pass NIL in the two longs if you don't want to change
  33.    those values.
  34. */
  35. void SetVars(Boolean saverOn, long oldGestaltAddr, long myAddr);
  36.  
  37. /*
  38.    myGestaltFunc() is the actual Gestalt handler.  This function actually
  39.    handles two different Gestalts:  the SAVR Gestalt, and my custom Gestalt,
  40.    named by the creator ID of my program.  The function knows which is
  41.    being handled by looking at the gestaltSelector parameter.
  42. */
  43. pascal OSErr myGestaltFunc(OSType gestaltSelector, long *gestaltResponse);
  44.  
  45. void main(long *gestaltAddr, long *setVarsAddr)
  46. {
  47.   long   oldA4;
  48.  
  49.   oldA4 = SetCurrentA4();
  50.   *gestaltAddr = ((long) myGestaltFunc);
  51.   *setVarsAddr = ((long) SetVars);
  52.   SetA4(oldA4);
  53. }
  54.  
  55. void SetVars(Boolean saverOn, long oldGestaltAddr, long myAddr)
  56. {
  57.   long   oldA4;
  58.  
  59.   oldA4 = SetCurrentA4();
  60.   gSaverOn = saverOn;
  61.   if (oldGestaltAddr != NIL)
  62.     gOldGestaltAddr = oldGestaltAddr;
  63.   if (myAddr != NIL)
  64.     gMyAddr = myAddr;
  65.   SetA4(oldA4);
  66. }
  67.  
  68. pascal OSErr myGestaltFunc(OSType gestaltSelector, long *gestaltResponse)
  69. {
  70.   OSErr     err;
  71.   long      oldA4;
  72.  
  73.   oldA4 = SetCurrentA4();
  74.  
  75.   if (gestaltSelector == 'SAVR')
  76.   {
  77.     if (gSaverOn)  // meaning that I need to handle this Gestalt
  78.     {
  79.       *gestaltResponse = kMySaverOn;
  80.       err = noErr;
  81.     }
  82.     else  // meaning that I need to call the Gestalt I replaced, if any
  83.     {
  84.       // if it's NIL, my SAVR Gestalt wan't installed over another SAVR Gestalt
  85.       if (gOldGestaltAddr != NIL)
  86.       {
  87.         // call the SAVR Gestalt that we replaced
  88.         err = ((GestaltFunctionPtr) gOldGestaltAddr) (gestaltSelector,
  89.                                                       gestaltResponse);
  90.       }
  91.       else  // I didn't replace one, so the saver is off
  92.       {
  93.         *gestaltResponse = kMySaverOff;
  94.         err = noErr;
  95.       }
  96.     }
  97.   }
  98.  
  99.   // change '????' to whatever your program's creator is.
  100.   // Then, by calling Gestalt with that code, the return value will
  101.   // contain the address of the code resource.
  102.   if (gestaltSelector == '????')
  103.   {
  104.     *gestaltResponse = gMyAddr;  // return address of code resource
  105.     err = noErr;
  106.   }
  107.  
  108.   SetA4(oldA4);
  109.   return err;
  110. }
  111.  
  112. /* ============ end SAVRGestalt.c ============ */
  113.  
  114.  
  115. Next, in your program, you include the following type definitions:
  116.  
  117. typedef pascal OSErr (*GestaltFunctionPtr) (OSType gestaltSelector,
  118.                                             long *gestaltResponse);
  119. typedef void (*GestaltInfoPtr) (long *gestaltAddr, long *setVarsAddr);
  120. typedef void (*GestaltSetVars) (Boolean saverOn, long oldGestaltAddr,
  121.                                 long myAddr);
  122.  
  123. The GestaltFunctionPtr is a pointer to a Gestalt selector function, the
  124. GestaltInfoPtr is a pointer to the main() function from the code resource,
  125. and GestaltSetVars is a pointer to the SetVars() function from the code
  126. resource.
  127.  
  128. Lastly, you'll want to declare the following functions:
  129.  
  130. void InstallGestalt(void)
  131. {
  132.   OSErr     gestaltErr;    // error returned by Gestalt
  133.   Handle gstFuncHandle;    // handle to Gestalt function
  134.   long      gestaltSelectorFunc;
  135.   long      result, setVarsProc;
  136.   ProcPtr   oldGestaltFunc = NIL;   // pointer to old Gestalt selector function
  137.  
  138.   // replace '????' with your creator ID
  139.   // The purpose of this call is to check and see if the code resource has
  140.   // already been installed.  If it has, gestaltErr returns noErr, and the
  141.   // result parameter contains a pointer to main() in the code resource.
  142.   // We go to this trouble because the program might have quit and restarted,
  143.   // in which case we don't know what's going on.
  144.   gestaltErr = Gestalt('????', &result);
  145.  
  146.   if (gestaltErr == noErr)
  147.   {
  148.     // call main(), returning addresses of myGestaltFunc() and SetVars()
  149.     ((GestaltInfoPtr) result) (&gestaltSelectorFunc, &setVarsProc);
  150.     // turn on our selector, without changing the addresses
  151.     ((GestaltSetVars) setVarsProc) (TRUE, NIL, NIL);
  152.   }
  153.   else  // it hasn't been installed, so let's install it
  154.   {
  155.     gstFuncHandle = GetResource('GDEF', 128);
  156.     if (ResError())
  157.       DeathAlert(errResource);
  158.     // DeathAlert() is my own error function.  The parameters are my own consts,
  159.     // and are defined elsewhere.  DeathAlert() calls ExitToShell at the end.
  160.     if ((gstFuncHandle == NIL) || (*gstFuncHandle == NIL))
  161.       DeathAlert(errNoFindGDEF);
  162.  
  163.     DetachResource(gstFuncHandle);
  164.     if (ResError())
  165.       DeathAlert(errResource);
  166.  
  167.   // We now call the function pointed to by the handle returned by GetResource.
  168.   // This seems strange -- keep in mind that this is really just the main()
  169.   // function.  We're calling it to get all the info we need.
  170.     ((GestaltInfoPtr) *gstFuncHandle) (&gestaltSelectorFunc, &setVarsProc);
  171.  
  172.     gestaltErr = NewGestalt('SAVR',
  173.                            NewSelectorFunctionProc(gestaltSelectorFunc));
  174.     if (gestaltErr != noErr)
  175.     {
  176.     // Could not add SAVR as a new selector.  Try to replace existing
  177. selector
  178.       gestaltErr = ReplaceGestalt('SAVR',
  179.                            NewSelectorFunctionProc(gestaltSelectorFunc),
  180.                            (SelectorFunctionProcPtr *) &oldGestaltFunc);
  181.       if (gestaltErr != noErr)
  182.         DeathAlert(errNoInstallSAVR);
  183.     }
  184.     ((GestaltSetVars) setVarsProc) (TRUE, (long) oldGestaltFunc,
  185.                                     (long) *gstFuncHandle);
  186.     /* TRUE to specify saver is on */
  187.     /* gOldGestaltFunc will be NIL if it wasn't replaced. */
  188.     /* *gstFuncHandle holds pointer to resource, which is locked, so we don't */
  189.     /*     have to worry about the dereferenced handle becoming invalid. */
  190.  
  191.     gestaltErr = NewGestalt('????',
  192.                            NewSelectorFunctionProc(gestaltSelectorFunc));
  193.     if (gestaltErr != noErr)
  194.       DeathAlert(errNoInstallCafe);
  195.   }
  196. }
  197.  
  198. void RemoveGestalt(void)
  199. {
  200.   OSErr     err;
  201.   long      response, selectorProc, setVarsProc;
  202.   ProcPtr   temp;
  203.  
  204.   // once again, we must assume that the program could have quit, so
  205.   // we don't know what's going on.  The rest should look very familiar
  206.   // if you've looked at the InstallGestalt() function.
  207.   err = Gestalt('????', &response);
  208.   if (err != noErr)
  209.     DeathAlert(errNoFindCafe);
  210.  
  211.   ((GestaltInfoPtr) response) (&selectorProc, &setVarsProc);
  212.   ((GestaltSetVars) setVarsProc) (FALSE, NIL, NIL);
  213. }
  214.  
  215.  
  216.  
  217.